package com.stars.services.impl.system;/**
 * Created by luodajie on 2019/1/5.
 */

import com.stars.common.base.BaseConstant;
import com.stars.common.base.ResultMsg;
import com.stars.common.cons.RedisCons;
import com.stars.common.date.DateUtil;
import com.stars.common.enums.RoleTypeEnum;
import com.stars.common.maps.JsonToMapUtils;
import com.stars.common.maps.JsonUtils;
import com.stars.dao.mapper.system.SysRoleMapper;
import com.stars.dao.mapper.system.SystemPermissionMapper;
import com.stars.dao.mapper.system.SystemUserMapper;
import com.stars.dao.mapper.system.SystemUserRelationMapper;
import com.stars.entity.dto.sys.SystemPermissionDTO;
import com.stars.entity.dto.sys.SystemUserAppOrgDTO;
import com.stars.entity.dto.system.SysRoleDTO;
import com.stars.entity.system.SysRoleEntity;
import com.stars.services.system.AuthAccessService;
import com.stars.services.system.SysRedisConfigServices;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author :dj
 * @version : 1.0.0
 * @description
 * @Date 2019-01-05 13:19
 * @note
 */
@Slf4j
@Service
public class AuthAccessServiceImpl implements AuthAccessService {
    @Autowired
    public SystemPermissionMapper systemPermissionMapper;
    @Autowired
    private SystemUserMapper systemUserMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    public SystemUserRelationMapper systemUserRelationMapper;
    @Autowired
    private SysRedisConfigServices sysRedisConfigServices;

    @Override
    public List<SystemPermissionDTO> findAllMenus(SystemPermissionDTO systemPermissionDTO) throws Exception {
        return getTree(findUserMenusList(systemPermissionDTO));
    }

    @Override
    public List<SystemPermissionDTO> findUserMenusList(SystemPermissionDTO systemPermissionDTO) throws Exception {
        if (systemPermissionDTO.getNullFlagQuery()) {
            systemPermissionDTO.setPid(BaseConstant.ROOT);
        }
        //如果是超级管理员，可以获取全部,否则只能拿到自己拥有的资源
        Boolean aBoolean = userIsRoot(systemPermissionDTO.getUserId());
        List<SystemPermissionDTO> list = new ArrayList<>();
        if (aBoolean) {
            systemPermissionDTO.setRoleId("");
            systemPermissionDTO.setUserId("");
            systemPermissionDTO.setOrgId("");
            List<SystemPermissionDTO> systemPermissionList = systemPermissionMapper.findByPerName(systemPermissionDTO);
            list = systemPermissionMapper.findAllMenusByEntity(systemPermissionList);
        } else {
            systemPermissionDTO.setPid("");
            list = findAllMenusList(systemPermissionDTO);
        }
        return list;
    }

    @Override
    public List<SystemPermissionDTO> findAllTreeMenusList(SystemPermissionDTO dto) throws Exception {
        return getTree(findAllMenusList(dto));
    }

    @Override
    public List<SystemPermissionDTO> findAllMenusList(SystemPermissionDTO dto) throws Exception {
        if (org.apache.commons.lang3.StringUtils.isBlank(dto.getUserId())) {
            return null;
        }
        SystemUserAppOrgDTO user = systemUserMapper.findByUserId(dto.getUserId());
        if (null == user) {
            return null;
        }
        //如果是超级用户
        if (userIsRoot(user.getId())) {
            dto.setUserId(user.getId());
            return findAllMenus(dto);
        }
        Map<String, SystemPermissionDTO> permissionDTOMap = new LinkedHashMap<>();
        List<SystemPermissionDTO> allTreeList = new LinkedList<>();
        //1，角色
        List<SysRoleDTO> sysRoleDTOList = user.getSysRoleDTOList();
        for (SysRoleDTO sysRoleDTO : sysRoleDTOList) {
            if (null == sysRoleDTO) {
                continue;
            }
            dto.setUserId("");
            dto.setRoleId(sysRoleDTO.getId());
            List<SystemPermissionDTO> roleList = systemPermissionMapper.findByRoleId(dto);
            if (null != roleList) {
                for (SystemPermissionDTO roleDto2 : roleList) {
                    permissionDTOMap.put(roleDto2.getId(), roleDto2);
                }
            }
            //如果有查询条件
            if (StringUtils.isNotBlank(dto.getPerName())) {
                List<SystemPermissionDTO> roleTreeList = systemPermissionMapper.findAllMenusByRoleId(roleList, dto.getRoleId());
                for (SystemPermissionDTO roleDto2 : roleTreeList) {
                    permissionDTOMap.put(roleDto2.getId(), roleDto2);
                }
            }
        }

        //----角色 end
        //2，用户个人资源
        dto.setRoleId("");
        dto.setUserId(user.getId());
        List<SystemPermissionDTO> userList = systemPermissionMapper.findPermissionByUserId(dto);
        if (null != userList) {
            for (SystemPermissionDTO userTree : userList) {
                permissionDTOMap.put(userTree.getId(), userTree);
            }
        }
        //如果有查询条件
        if (StringUtils.isNotBlank(dto.getPerName())) {
            List<SystemPermissionDTO> userTreeList = systemPermissionMapper.findTreePermissionListByUserId(userList, dto.getUserId());
            for (SystemPermissionDTO userTree : userTreeList) {
                permissionDTOMap.put(userTree.getId(), userTree);
            }
        }
        //3,组织
        if (StringUtils.isNotBlank(user.getOrgId())) {
            dto.setOrgId(user.getOrgId());
            dto.setUserId("");
            dto.setRoleId("");
            List<SystemPermissionDTO> orgList = systemPermissionMapper.findPermissionByOrgId(dto);
            if (null != orgList) {
                for (SystemPermissionDTO orgDto1 : orgList) {
                    permissionDTOMap.put(orgDto1.getId(), orgDto1);
                }
            }
            //如果有查询条件
            if (StringUtils.isNotBlank(dto.getPerName())) {
                List<SystemPermissionDTO> orgTreeList = systemPermissionMapper.findTreePermissionListByOrgId(orgList, dto.getOrgId());
                for (SystemPermissionDTO orgDto1 : orgTreeList) {
                    permissionDTOMap.put(orgDto1.getId(), orgDto1);
                }
            }
        }
        permissionDTOMap.forEach((key, value) -> {
            allTreeList.add(value);
        });
        return allTreeList;
    }

    @Override
    public List<SystemPermissionDTO> findByRoleId(SystemPermissionDTO dto) throws Exception {
        if (StringUtils.isBlank(dto.getRoleId())) {
            return null;
        }
        SysRoleEntity sysRoleEntity = sysRoleMapper.selectByPrimaryKey(dto.getRoleId());
        //如果是超级管理员，查询所有菜单
        if (RoleTypeEnum.ROOT_ROLE.getValue().equals(sysRoleEntity.getRoleType())) {
            dto.setUserId("");
            dto.setRoleId("");
            dto.setOrgId("");
            if (StringUtils.isBlank(dto.getPerName())) {
                dto.setPid(BaseConstant.ROOT);
            }
            List<SystemPermissionDTO> systemPermissionList = systemPermissionMapper.findByPerName(dto);
            List<SystemPermissionDTO> list = systemPermissionMapper.findAllMenusByEntity(systemPermissionList);
            return getTree(list);
        }
        List<SystemPermissionDTO> list = systemPermissionMapper.findByRoleId(dto);
        if (StringUtils.isNotBlank(dto.getPerName())) {
            List<SystemPermissionDTO> treeList = systemPermissionMapper.findAllMenusByRoleId(list, dto.getRoleId());
            return getTree(treeList);
        }
        return getTree(list);
    }

    @Override
    public List<SystemPermissionDTO> findUserMenusTreeList(SystemPermissionDTO dto) throws Exception {
        if (StringUtils.isBlank(dto.getUserId())) {
            return null;
        }
        List<SystemPermissionDTO> list = systemPermissionMapper.findPermissionByUserId(dto);
        if (StringUtils.isNotBlank(dto.getPerName())) {
            List<SystemPermissionDTO> treeList = systemPermissionMapper.findTreePermissionListByUserId(list, dto.getUserId());
            return getTree(treeList);
        }
        return getTree(list);
    }

    @Override
    public List<SystemPermissionDTO> findOrgMenusTreeList(SystemPermissionDTO dto) throws Exception {
        if (StringUtils.isBlank(dto.getOrgId())) {
            return null;
        }
        List<SystemPermissionDTO> list = systemPermissionMapper.findPermissionByOrgId(dto);
        if (StringUtils.isNotBlank(dto.getPerName())) {
            List<SystemPermissionDTO> treeList = systemPermissionMapper.findTreePermissionListByOrgId(list, dto.getOrgId());
            return getTree(treeList);
        }
        return getTree(list);
    }

    @Override
    public List<String> getBtn(String userId, String bntType) throws Exception {
        if (StringUtils.isBlank(userId)) {
            return null;
        }
        List<String> btnList = new ArrayList<>();
        SystemPermissionDTO dto = new SystemPermissionDTO();
        dto.setPerType(bntType);
        List<SystemPermissionDTO> systemPermissionList = new ArrayList<>();
        if (userIsRoot(userId)) {
            systemPermissionList = systemPermissionMapper.findByPerName(dto);

        } else {
            dto.setUserId(userId);
            systemPermissionList = findAllMenusList(dto);
        }
        if (null != systemPermissionList) {
            /** 遍历根据角色id查询资源列表 **/
            for (SystemPermissionDTO btnDto : systemPermissionList) {
                if (StringUtils.isBlank(btnDto.getPerBtnValid())) {
                    continue;
                }
                btnList.add(btnDto.getPerBtnValid());
            }
        }
        return btnList;
    }

    private List<SystemPermissionDTO> getTree(List<SystemPermissionDTO> list) {
        //首先将list转map映射
        Map<String, SystemPermissionDTO> map = new HashMap<>();
        List<SystemPermissionDTO> systemPermissionDTOList = new ArrayList<>();
        //循环生成Tree
        if (null == list) {
            return null;
        }
        for (SystemPermissionDTO dto : list) {
            map.put(dto.getId(), dto);
            if (dto.getLayer() < 3) {
                dto.setExpanded(true);
            }
            //如果存在父节点，那么获取父节点，并将自己加入父节点
            if (StringUtils.isNotBlank(dto.getPid()) && !BaseConstant.ROOT.equals(dto.getPid())) {
                if(map.get(dto.getPid()) != null){
                    map.get(dto.getPid()).getChildren().add(dto);
                }
            } else {
                systemPermissionDTOList.add(dto);
            }
        }

        return systemPermissionDTOList;
    }

    @Override
    public ResultMsg authLogin(String userId, String token) throws Exception {

        log.info("单点模块开始==================================");
        /** 重新登录后，先检查redis中是否存在，之前的用户数据 **/
        //根据用户id获取token
        String sToken = sysRedisConfigServices.get(userId);
        log.info("根据用户id获取token:" + sToken + "--");
        authOutLogin(sToken);
        SystemUserAppOrgDTO userDto = systemUserMapper.findByUserId(userId);
        /** 登录成功，将token加入redis **/
        //设置过期时间为7天
        sysRedisConfigServices.set(token, userId);
        //设置过期时间为7天
        sysRedisConfigServices.set(userId, token);
        //存用户信息
        sysRedisConfigServices.set(userId + BaseConstant.ACCESS_TOKEN, JsonUtils.objectToJson(userDto));
        log.info("单点模块结束==================================");
        //设置过期时间为10秒
        //redisTemplate.opsForValue().set(token,systemUser.getId(), 10, TimeUnit.SECONDS);
        SystemPermissionDTO dto = new SystemPermissionDTO();
        dto.setUserId(userId);
        List<SystemPermissionDTO> permissions = findUserMenusList(dto);
        //添加菜单地址到Redis
        Map<String, Object> urlMap = new HashMap<>();
        permissions.forEach(per -> {
            if (StringUtils.isNotBlank(per.getPerUrl())) {
                urlMap.put(per.getPerUrl(), per.getPerName());
            }
        });

        sysRedisConfigServices.set(RedisCons.MENU_USER_URL + userId, JsonToMapUtils.mapToJson(urlMap));
        sysRedisConfigServices.set(RedisCons.USER_LOGIN_DATE + userId, DateUtil.getNewTime() + "");
        List<String> roleNames = new ArrayList<>();
        if (null != userDto.getSysRoleDTOList()) {
            for (SysRoleDTO sysRoleDTO : userDto.getSysRoleDTOList()) {
                roleNames.add(sysRoleDTO.getRoleName());
            }
        }
        userDto.setRoleNames(roleNames);
        Map<String, Object> map = new HashMap<>();
        map.put(BaseConstant.TOKEN_NAME, token);
        map.put(BaseConstant.TOKEN_USER, userDto);
        map.put(BaseConstant.PERMISSIONS, getTree(permissions));
        return ResultMsg.success(map);
    }

    @Override
    public void authOutLogin(String sToken) throws Exception {
        if (null != sToken) {
            //根据token获取用户id
            String sUserId = sysRedisConfigServices.get(sToken);
            log.info("根据token获取用户id:" + sUserId + "--");
            /** 重新登录后，删除已经存在redis的用户信息，确保唯一 **/
            sysRedisConfigServices.delByKey(sToken);
            log.info("删除token:" + sToken);
            if (sUserId != null) {
                sysRedisConfigServices.delByKey(sUserId);
                sysRedisConfigServices.delByKey(sUserId + BaseConstant.ACCESS_TOKEN);
                sysRedisConfigServices.delByKey(sUserId + "_" + BaseConstant.PER_MENU);
                sysRedisConfigServices.delByKey(sUserId + "_" + BaseConstant.PER_BTN);
                sysRedisConfigServices.delByKey(RedisCons.MENU_USER_URL + sUserId);
                sysRedisConfigServices.delByKey(RedisCons.USER_LOGIN_DATE + sUserId);
                log.info("删除UserId:" + sUserId);
            }
        }
    }

    @Override
    public Boolean userIsRoot(String userId) throws Exception {
        if (StringUtils.isBlank(userId)) {
            return false;
        }
        SystemUserAppOrgDTO systemUser = sysRedisConfigServices.getByKeyToPojo(userId + BaseConstant.ACCESS_TOKEN, SystemUserAppOrgDTO.class);
        if (null == systemUser) {
            return false;
        }
        if (null == systemUser.getSysRoleDTOList()) {
            return false;
        }
        for (SysRoleDTO sysRoleDTO : systemUser.getSysRoleDTOList()) {
            if (null != sysRoleDTO.getRoleType()) {
                Integer roleType = new Integer(sysRoleDTO.getRoleType());
                if(RoleTypeEnum.ROOT_ROLE.getValue().equals(roleType)){
                    return true;
                }
            }
        }
        return false;
    }
}
